package fr.castorhoz.isi_connectivity_widget.mobiledata_widget;

import java.util.ArrayList;
import java.util.List;

import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.NetworkInfo.DetailedState;
import android.provider.Settings;
import android.util.Log;
import fr.castorhoz.isi_connectivity_widget.ConnBroadcastReceiver;
import fr.castorhoz.isi_connectivity_widget.ConnButton;
import fr.castorhoz.isi_connectivity_widget.database.DBAdapter;

/**
 * @author HozakaN
 *
 */
public class MobileDataBroadcastReceiver extends ConnBroadcastReceiver {
	
	private static final boolean DEBUG_DIAGNOSTIC = false;
	
	protected static List<Integer> appWidgetIds = new ArrayList<Integer>();
	
	private DBAdapter dbAdapter;

	public MobileDataBroadcastReceiver(/*ConnButton button, */Context context) {
		super(context); //button);
		dbAdapter = new DBAdapter(context);
		dbAdapter.open();
		appWidgetIds = dbAdapter.getAppWidgetIdUsingWidget(ConnButton.widgets.mobileDataWidget.name());
		dbAdapter.close();
	}
	
	/**
	 * Adds the appWidget to the ones that need to be notified when the broadcast receiver receives an event
	 * @param appWidgetId
	 */
	public static void addAppWidget(int appWidgetId) {
		Log.d(MobileDataBroadcastReceiver.class.getName(), "adding appWidgetId "+appWidgetId+" to MobileDataBroadcastReceiver");
		appWidgetIds.add(appWidgetId);
		if (appWidgetIds.size() == 1) {
			//The first appWidget has been listed, we need to listen to broadcast for connectivity changes
			//FIXME since registerItself is a object method, we cannot use it right here
		}
	}
	
	@Override
	public void doOnReceive(Context context, Intent intent) {
		if (DEBUG_DIAGNOSTIC) {
			diagnosticNetwork(context, intent);
		}
		
		final String action = intent.getAction();
		if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
			//NetworkInfo nInfo = (NetworkInfo) intent.getExtras().get(ConnectivityManager.EXTRA_NETWORK_INFO);
			ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
			NetworkInfo nInfo = cm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
			if (nInfo != null) {
				detectMobileDataConnectivityState(nInfo);
			}
		}
	}
	
	/**
	 * Calculates the state of mobileData network, and saves it into the database
	 * @param nInfo
	 */
	private void detectMobileDataConnectivityState(NetworkInfo nInfo) {
		if (nInfo.getType() == ConnectivityManager.TYPE_MOBILE) {
			if (!nInfo.getReason().equals("gprsAttached")) { //we don't catch this event since it triggers CONNECTIVITY_ACTION at anytime
				boolean previousState = MobileDataButton.getMobileDataStateFromDatabse(context);
				Log.d(this.getClass().getName(), "mobile data Detaield state : "+nInfo.getDetailedState().name());
				if (nInfo.getDetailedState().equals(DetailedState.DISCONNECTED)) {
					String reason = nInfo.getReason();
					if (reason.equals(MobileDataButton.DATA_DISABLED) && previousState) {
						dbAdapter.open();
						dbAdapter.removeMobileDataWidgetStates();
						dbAdapter.insertMobileDataWidgetState(MobileDataButton.DATA_DISABLED);
						dbAdapter.close();
						hasChanged();
					}
				} else if (nInfo.isConnectedOrConnecting() && !previousState) {
					dbAdapter.open();
					dbAdapter.removeMobileDataWidgetStates();
					dbAdapter.insertMobileDataWidgetState(MobileDataButton.DATA_ENABLED);
					dbAdapter.close();
					hasChanged();
				}
			}
		}
	}

	/**
	 * Debug purposes. DEFAULT_NETWORK_PREFERENCE often is WIFI
	 * @param mContext
	 * @return
	 */
	private static int getPersistedNetworkPreference(Context mContext) {
        final ContentResolver cr = mContext.getContentResolver();

        final int networkPrefSetting = Settings.Secure
                .getInt(cr, Settings.Secure.NETWORK_PREFERENCE, -1);
        if (networkPrefSetting != -1) {
            return networkPrefSetting;
        }

        return ConnectivityManager.DEFAULT_NETWORK_PREFERENCE;
    }
	
	public static void diagnosticNetwork(Context context, Intent intent) {
		final String action = intent.getAction();

		Log.d(MobileDataBroadcastReceiver.class.getName(), "intent mobile_data : " + action);
		ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
		Log.d(MobileDataBroadcastReceiver.class.getName(), "connectivity preference : "+cm.getNetworkPreference());
		Log.d(MobileDataBroadcastReceiver.class.getName(), "TYPE_MOBILE : "+ConnectivityManager.TYPE_MOBILE);
		Log.d(MobileDataBroadcastReceiver.class.getName(), "TYPE_WIFI : "+ConnectivityManager.TYPE_WIFI);
	    int netWorkPref = getPersistedNetworkPreference(context);
	    Log.d(MobileDataBroadcastReceiver.class.getName(), "network preference : "+netWorkPref);
		if (intent.getAction().equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
		    NetworkInfo nInfo = (NetworkInfo) intent.getExtras().get(ConnectivityManager.EXTRA_NETWORK_INFO);

		    if (nInfo != null) {
				Log.d(MobileDataBroadcastReceiver.class.getName(), "detailedInfoState : "+nInfo.getDetailedState().name());
				Log.d(MobileDataBroadcastReceiver.class.getName(), "reason : "+nInfo.getReason());
				Log.d(MobileDataBroadcastReceiver.class.getName(), "typeName : "+nInfo.getTypeName());
				Log.d(MobileDataBroadcastReceiver.class.getName(), "subtypeName : "+nInfo.getSubtypeName());
				Log.d(MobileDataBroadcastReceiver.class.getName(), "extraInfo : "+nInfo.getExtraInfo());
		        Log.d(MobileDataBroadcastReceiver.class.getName(), "State : "+nInfo.getState().toString());
		        Log.d(MobileDataBroadcastReceiver.class.getName(), "isConnected : "+(nInfo.isConnected() ? "true" : "false"));
		        Log.d(MobileDataBroadcastReceiver.class.getName(), "isConnectedOrConnecting : "+(nInfo.isConnectedOrConnecting() ? "true" : "false"));

		        Log.d(MobileDataBroadcastReceiver.class.getName(), "=========== Extra extra info ==========");
		        /*nInfo = (NetworkInfo)intent.getExtras().get(ConnectivityManager.EXTRA_EXTRA_INFO);
		        if (nInfo != null) {
					Log.d(MobileDataBroadcastReceiver.class.getName(), "detailedInfoState : "+nInfo.getDetailedState().name());
					Log.d(MobileDataBroadcastReceiver.class.getName(), "reason : "+nInfo.getReason());
					Log.d(MobileDataBroadcastReceiver.class.getName(), "typeName : "+nInfo.getTypeName());
					Log.d(MobileDataBroadcastReceiver.class.getName(), "subtypeName : "+nInfo.getSubtypeName());
					Log.d(MobileDataBroadcastReceiver.class.getName(), "extraInfo : "+nInfo.getExtraInfo());
			        Log.d(MobileDataBroadcastReceiver.class.getName(), "State : "+nInfo.getState().toString());
			        Log.d(MobileDataBroadcastReceiver.class.getName(), "isConnected : "+(nInfo.isConnected() ? "true" : "false"));
			        Log.d(MobileDataBroadcastReceiver.class.getName(), "isConnectedOrConnecting : "+(nInfo.isConnectedOrConnecting() ? "true" : "false"));
		        }*/
		        Log.d(MobileDataBroadcastReceiver.class.getName(), "=====================");
		        
		        Log.d(MobileDataBroadcastReceiver.class.getName(), "=========== Extra other network info ==========");
		        nInfo = (NetworkInfo)intent.getExtras().get(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO);
		        if (nInfo != null) {
					Log.d(MobileDataBroadcastReceiver.class.getName(), "detailedInfoState : "+nInfo.getDetailedState().name());
					Log.d(MobileDataBroadcastReceiver.class.getName(), "reason : "+nInfo.getReason());
					Log.d(MobileDataBroadcastReceiver.class.getName(), "typeName : "+nInfo.getTypeName());
					Log.d(MobileDataBroadcastReceiver.class.getName(), "subtypeName : "+nInfo.getSubtypeName());
					Log.d(MobileDataBroadcastReceiver.class.getName(), "extraInfo : "+nInfo.getExtraInfo());
			        Log.d(MobileDataBroadcastReceiver.class.getName(), "State : "+nInfo.getState().toString());
			        Log.d(MobileDataBroadcastReceiver.class.getName(), "isConnected : "+(nInfo.isConnected() ? "true" : "false"));
			        Log.d(MobileDataBroadcastReceiver.class.getName(), "isConnectedOrConnecting : "+(nInfo.isConnectedOrConnecting() ? "true" : "false"));
		        }
		        Log.d(MobileDataBroadcastReceiver.class.getName(), "=====================");
		    } else {
		        Log.d(MobileDataBroadcastReceiver.class.getName(), "nInfo null");
		    }
		}
	}

	@Override
	protected List<Integer> getAppWidgetIds() {
		return appWidgetIds;
	}

//	@Override
//	protected void registerItself(Context context) {
//		//IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
//		//context.getApplicationContext().registerReceiver(this, filter);
//		//Log.d(this.getClass().getName(), "broadcast receiver "+this.getClass().getSimpleName()+" has registered itself");
//	}

	@Override
	public String getBroadcastAction() {
		return ConnectivityManager.CONNECTIVITY_ACTION;
	}

	@Override
	protected String getWidgetName() {
		return ConnButton.widgets.mobileDataWidget.name();
	}

}
